home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / dviware / umddvi / lib / seek.c < prev    next >
C/C++ Source or Header  |  1990-10-01  |  3KB  |  135 lines

  1. /*
  2.  * Copyright (c) 1987 University of Maryland Department of Computer Science.
  3.  * All rights reserved.  Permission to copy for any purpose is hereby granted
  4.  * so long as this copyright notice remains intact.
  5.  */
  6.  
  7. #ifndef lint
  8. static char rcsid[] = "$Header: seek.c,v 2.4 87/06/16 18:29:03 chris Exp $";
  9. #endif
  10.  
  11. /*
  12.  * Seekable is a predicate which returns true iff a Unix fd is seekable.
  13.  *
  14.  * MakeSeekable forces an input stdio file to be seekable, by copying to
  15.  * a temporary file if necessary.
  16.  */
  17.  
  18. #include <stdio.h>
  19. #ifdef sys5
  20. #include <sys/types.h>
  21. #include <sys/fcntl.h>
  22. #else
  23. #include <sys/param.h>
  24. #endif
  25. #include <sys/file.h>
  26. #include <sys/stat.h>
  27.  
  28. long    lseek();
  29. char    *getenv();
  30.  
  31. int
  32. Seekable(fd)
  33.     int fd;
  34. {
  35.  
  36.     return (lseek(fd, 0L, 1) >= 0 && !isatty(fd));
  37. }
  38.  
  39. /*
  40.  * We use the despicable trick of unlinking an open temporary file.
  41.  * The alternatives are too painful.  If it becomes necessary to
  42.  * do this another way, however, here is a method suggested by Fred
  43.  * Blonder: fork, and have the parent wait for the child to exit.
  44.  * (The parent must avoid being killed during this phase.)  When
  45.  * the child exits, the parent should then remove the temporary file,
  46.  * then exit with the same status, or send itself the same signal.
  47.  */
  48. int
  49. MakeSeekable(f)
  50.     register FILE *f;
  51. {
  52.     register int tf, n;
  53.     int mypid, tries, blksize;
  54.     char *tmpdir;
  55. #ifdef MAXBSIZE
  56.     char buf[MAXBSIZE];
  57.     struct stat st;
  58. #else
  59.     char buf[BUFSIZ];
  60. #endif
  61.  
  62.     if (Seekable(fileno(f)))
  63.         return (0);
  64.  
  65.     if ((tmpdir = getenv("TMPDIR")) == 0)
  66.         tmpdir = "/tmp";
  67.  
  68.     /* compose a suitable temporary file name, and get an r/w descriptor */
  69.     mypid = getpid();
  70.     n = 0;
  71.     tries = 0;
  72.     do {
  73.         sprintf(buf, "%s/#%d.%d", tmpdir, mypid, n++);
  74.         (void) unlink(buf);
  75. #ifdef O_CREAT            /* have three-argument open syscall */
  76.         tries++;
  77.         tf = open(buf, O_RDWR | O_CREAT | O_EXCL, 0666);
  78. #else
  79.         if (access(buf, 0) == 0) {
  80.             /*
  81.              * Skip existing files.  Note that tf might
  82.              * not be set yet.
  83.              */
  84.             tf = -1;
  85.             continue;
  86.         }
  87.         tries++;
  88.         tf = creat(buf, 0666);
  89.         if (tf >= 0) {
  90.             (void) close(tf);
  91.             tf = open(buf, 2);
  92.             if (tf < 0)
  93.                 (void) unlink(buf);
  94.         }
  95. #endif
  96.     } while (tf < 0 && tries < 20);
  97.     if (tf < 0)        /* probably unrecoverable user error */
  98.         return (-1);
  99.  
  100.     (void) unlink(buf);
  101.  
  102.     /* copy from input file to temp file */
  103. #ifdef MAXBSIZE
  104.     if (fstat(tf, &st))    /* how can this ever fail? */
  105.         blksize = MAXBSIZE;
  106.     else
  107.         blksize = MIN(MAXBSIZE, st.st_blksize);
  108. #else
  109.     blksize = BUFSIZ;
  110. #endif
  111.     while ((n = fread(buf, 1, blksize, f)) > 0) {
  112.         if (write(tf, buf, n) != n) {
  113.             (void) close(tf);
  114.             return (-1);
  115.         }
  116.     }
  117.     /* ferror() is broken in Ultrix 1.2; hence the && */
  118.     if (ferror(f) && !feof(f)) {
  119.         (void) close(tf);
  120.         return (-1);
  121.     }
  122.  
  123.     /*
  124.      * Now switch f to point at the temp file.  Since we hit EOF, there
  125.      * is nothing in f's stdio buffers, so we can play a dirty trick: 
  126.      */
  127.     clearerr(f);
  128.     if (dup2(tf, fileno(f))) {
  129.         (void) close(tf);
  130.         return (-1);
  131.     }
  132.     (void) close(tf);
  133.     return (0);
  134. }
  135.